package org.codehaus.activemq.transport.tcp;

import java.io.EOFException;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class TcpBufferedOutputStream extends FilterOutputStream
{
  private static final int BUFFER_SIZE = 4096;
  private byte[] buf;
  private int count;

  public TcpBufferedOutputStream(OutputStream out)
  {
    this(out, 4096);
  }

  public TcpBufferedOutputStream(OutputStream out, int size)
  {
    super(out);
    if (size <= 0) {
      throw new IllegalArgumentException("Buffer size <= 0");
    }
    this.buf = new byte[size];
  }

  public void write(int b)
    throws IOException
  {
    checkClosed();
    if (availableBufferToWrite() < 1) {
      flush();
    }
    this.buf[(this.count++)] = (byte)b;
  }

  public void write(byte[] b, int off, int len)
    throws IOException
  {
    checkClosed();
    if (availableBufferToWrite() < len) {
      flush();
    }
    if (this.buf.length >= len) {
      System.arraycopy(b, off, this.buf, this.count, len);
      this.count += len;
    }
    else {
      this.out.write(b, off, len);
    }
  }

  public void flush()
    throws IOException
  {
    if ((this.count > 0) && (this.out != null)) {
      this.out.write(this.buf, 0, this.count);
      this.count = 0;
    }
  }

  public void close()
    throws IOException
  {
    super.close();
    this.out = null;
    this.buf = null;
  }

  protected void checkClosed()
    throws IOException
  {
    if ((this.buf == null) || (this.out == null))
      throw new EOFException("Cannot write to the stream any more it has already been closed");
  }

  private int availableBufferToWrite()
  {
    return this.buf.length - this.count;
  }
}